import {retry} from 'rxjs/operators';
import {Injectable} from "@angular/core";
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from "@angular/common/http";
import {Observable, Subject} from "rxjs";
import {Setting} from "../public/setting/setting";
import {ResponseError} from "../public/setting/model";

@Injectable()
export class ResponseInterceptor implements HttpInterceptor {

  constructor() {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const interceptObservable: Subject<HttpEvent<any>> = new Subject();

    // extend server response observable with logging
    next.handle(req)
      .pipe(
        retry(Setting.responseRetryTime),
      )
      .subscribe(event => {
        ResponseInterceptor.handleSuccessResponse(event, interceptObservable);
      }, error => {
        return ResponseInterceptor.handleErrorResponse(error, interceptObservable);
      });
    return interceptObservable;
  }

  /**
   * Apis in webide-backend report some error-info in successResponse. eg: {success: false, info: '', data: null, code: ''}
   * @param event
   * @param interceptObservable
   */
  protected static handleSuccessResponse(event: HttpEvent<any>, interceptObservable: Subject<HttpEvent<any>>): void {
    if (event instanceof HttpResponse) {
      if (event.body && event.body.success === false) {
        const errorObservable = new Subject();
        const errorBody: ResponseError = {
          code: event.body.code,
          message: event.body.info,
          name: event.body.code,
          statusCode: event.status
        };
        const errorResponse = new HttpErrorResponse({
          headers: event.headers,
          status: event.status,
          error: {
            error: errorBody
          }
        });
        errorObservable.complete();
        interceptObservable.error(errorResponse);
        interceptObservable.complete();
      } else {
        interceptObservable.next(event);
        interceptObservable.complete();
      }
    }
  }

  protected static handleErrorResponse(error: any, interceptObservable: Subject<HttpEvent<any>>): Observable<any> {
    if(!error.url){
      const errorResponse = new HttpErrorResponse({
        headers: error.headers,
        status: error.status,
        error: {
          error: {
            code: error.status,
            message: error.message,
            name: error.name,
            statusCode: error.statusText
          }
        }
      });
      interceptObservable.error(errorResponse);
      interceptObservable.complete();
      return interceptObservable;
    }
    interceptObservable.error(error);
    interceptObservable.complete();
    return interceptObservable;
  }
}
